package com.aliware.tianchi;

import org.apache.dubbo.rpc.Invoker;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * Description:
 * Date: 19-6-27
 *
 * @author ujued
 */
@Deprecated
public class Counter {

    private static Map<Invoker, InvokerInfo> invokerInfoMap = new ConcurrentHashMap<>();
    private static volatile boolean overTest = false;


    @SuppressWarnings("unchecked")
    public static <T> Invoker<T> select(List<Invoker<T>> invokers) {
        if (invokerInfoMap.isEmpty()) {
            invokers.forEach(invoker -> invokerInfoMap.put(invoker, new InvokerInfo(invoker.getUrl().getHost())));
        }
        if (overTest) {
            for (Map.Entry<Invoker, InvokerInfo> entry : invokerInfoMap.entrySet()) {
                if (entry.getValue().remainReq.getAndDecrement() >= 0) {
                    return entry.getKey();
                }
            }
            throw new IllegalStateException("Server non provider... 501");
        }
        for (Map.Entry<Invoker, InvokerInfo> entry : invokerInfoMap.entrySet()) {
            if (!entry.getValue().overTest) {
                entry.getValue().maxReq.incrementAndGet();
                entry.getValue().remainReq.incrementAndGet();
                return entry.getKey();
            }
        }
        overTest = true;
        throw new IllegalStateException("Server ready over testing... 501");
    }

    public static void stopTest(Invoker<?> invoker) {
        System.out.println("Stop test: " + invoker);
        invokerInfoMap.get(invoker).overTest = true;
    }

    public static void release(Invoker<?> invoker) {
        InvokerInfo invokerInfo = invokerInfoMap.get(invoker);
        if (invokerInfo.remainReq.get() < invokerInfo.maxReq.get()) {
            invokerInfoMap.get(invoker).remainReq.incrementAndGet();
        }
    }

    public static String invokersInfo() {
        return invokerInfoMap.values().stream().map(Object::toString).collect(Collectors.joining(","));
    }

    public static class InvokerInfo {
        private String name;
        private volatile boolean overTest = false;
        private AtomicInteger maxReq = new AtomicInteger(0);
        private AtomicInteger remainReq = new AtomicInteger(0);

        public InvokerInfo(String name) {
            this.name = name;
        }

        @Override
        public String toString() {
            return name + "[max: " + maxReq + ", remain: " + remainReq + "]";
        }
    }
}
